/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.workplicity.marist.grounds.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.workplicity.entry.Service;
import org.workplicity.entry.User;
import org.workplicity.entry.WorkRequest;
import org.workplicity.entry.WorkSlate;
import org.workplicity.entry.event.Event;

/**
 * @author Stephen Horn & Elliott Picker
 */
public class Warn {

    /**
     * This method checks the Accounts repository for duplicate user Lognames
     * @param users an ArrayList of all users
     */
    public static void checkDuplicateNames(ArrayList<User> users) {

        //This for loop iterates through the users, comparing them to each other
        for (int outer = 0; outer < users.size() - 1; outer++) {
            //suspect is user which will be compared to each other user
            User suspect = users.get(outer);
            //The inner for loop retrieves each user in the list of users after
            //the suspect user and compares their lognames. If a duplicate is
            //found, it is added to the report
            for (int inner = outer + 1; inner < users.size(); inner++) {
                if (suspect.getLogname().equals(users.get(inner).getLogname())) {
                    Report.add(Report.alertType.usersWithIdenticalLogNames, suspect.toString());
                }
            }
        }
    }

    /**
     * This method checks to see if any user has no Services
     * @param users an ArrayList of all users
     */
    public static void checkUserNoService(ArrayList<User> users) {

        //This for loop will iterate through the list of users, checking the size
        //of each user's ServiceList. If empty, that user will be added to the report.
        for (int i = 0; i < users.size(); i++) {
            User suspect = users.get(i);
            if (suspect.getServiceList().isEmpty()) {
                Report.add(Report.alertType.usersWithoutServices, suspect.toString());
            }
        }
    }

    /**
     * This method checks to see if there are any Services which do not have users
     * @param services an ArrayList of all services
     * @param users an ArrayList of all users
     */
    public static void checkServiceNoUser(ArrayList<Service> services, ArrayList<User> users) {

        //This for loop iterates through the list of users
        for (int outer = 0; outer < users.size(); outer++) {
            //serviceCheck contains the unique ids of the current user's ServiceList
            List<Integer> serviceCheck = users.get(outer).getServiceList();
            //The inner for loop iterates through the list of all services. If
            //the current user's ServiceList contains any service from the list of
            //all services, that service is removed from that list. This effectively
            //removes any service which has a user from the original list, leaving
            //only those that do not contain any users.
            for (int inner = 0; inner < services.size(); inner++) {
                if (serviceCheck.contains(services.get(inner).getId())) {
                    services.remove(inner);
                }
            }
        }
        for (int i = 0; i < services.size(); i++) {
            Report.add(Report.alertType.servicesWithoutUsers, services.get(i).toString());
        }
    }

    /**
     * This method checks if any user has an invalid or missing Logname
     * @param users an ArrayList of all users
     */
    public static void invalidLogname(ArrayList<User> users) {

        //The INVALID string contains the characters which, if contained by a
        //user's logname, cause the logname to be considered invalid
        String INVALID = " !_@#$%&*[](){}:;\"\'<>?/~.,`";

        //This for loop iterates through the list of users
        for (int outer = 0; outer < users.size(); outer++) {
            //currentUser is the user at the current iteration of the for loop
            User currentUser = users.get(outer);
            //logname is the Logname of the current user
            String logname = currentUser.getLogname();
            //The inner for loop checks to see if the current logname contains
            //any characters found in the string INVALID
            for (int inner = 0; inner < INVALID.length(); inner++) {
                if (logname.indexOf(INVALID.charAt(inner)) != -1) {
                    Report.add(Report.alertType.invalidOrMissingLogName, currentUser.toString());
                }
            }
        }

        //This for loop checks to see if any user's logname is equal to an empty
        //string, which would cause its logname to be considered missing
        for (int loop = 0; loop < users.size(); loop++) {
            User currentUser = users.get(loop);
            String logname = currentUser.getLogname();
            if (logname.equals("")) {
                Report.add(Report.alertType.invalidOrMissingLogName, currentUser.toString());
            }
        }
    }

    /**
     * This method checks user password to see if they are invalid or insecure
     * @param users an ArrayList of all users
     */
    public static void invalidPassword(ArrayList<User> users) {

        //The INVALID string contains the characters which, if contained by a
        //user's password, cause the password to be considered invalid
        String INVALID = " !_@#$%&*[](){}:;\"\'<>?/~.,`";

        //This for loop iterates through the list of users
        for (int outer = 0; outer < users.size(); outer++) {
            //currentUser is the user at the current iteration of the for loop
            User currentUser = users.get(outer);
            //password is the Password of the current user
            String password = currentUser.getPassword();
            //This if statement determines if a password is too short
            if (password.length() < 3) {
                Report.add(Report.alertType.invalidPassword, currentUser.toString());
                continue;
            }
            //This if statement checks if the user's password is equal to their
            //logname
            if (password.equals(currentUser.getLogname())) {
                Report.add(Report.alertType.invalidPassword, currentUser.toString());
                continue;
            }
            //The inner for loop checks to see if the current password contains
            //any characters found in the string INVALID
            for (int inner = 0; inner < INVALID.length(); inner++) {
                if (password.indexOf(INVALID.charAt(inner)) != -1) {
                    Report.add(Report.alertType.invalidPassword, currentUser.toString());
                }
            }
        }
    }

    /**
     * This method looks through the repositories and determines if any entries have identical Ids
     * @param CHlist an ArrayList representing the ClearingHouse repository
     * @param SRlist an ArrayList representing the Services repository
     * @param WSlist an ArrayList representing the WorkSlates repository
     * @param AClist an ArrayList representing the Accounts repository
     * @param FUlist an ArrayList representing the Futures repository
     */
    public static void duplicateIds(ArrayList<WorkRequest> clearingHouse, ArrayList<Service> services, ArrayList<WorkSlate> workslates, ArrayList<User> accounts, ArrayList<Event> futures) {

        //Check if any workslates have identical ids

        for (int outer = 0; outer < workslates.size() - 1; outer++) {
            for (int inner = outer + 1; inner < workslates.size(); inner++) {
                if (workslates.get(inner).getId().equals(workslates.get(outer).getId())) {
                    Report.add(Report.alertType.duplicateIds, "In repository Workslates: " + (workslates.get(inner) + " and " + workslates.get(outer)));
                }
            }
        }

        // Check if any users have identical ids

        for (int outer = 0; outer < accounts.size() - 1; outer++) {
            for (int inner = outer + 1; inner < accounts.size(); inner++) {
                if (accounts.get(inner).getId().equals(accounts.get(outer).getId())) {
                    Report.add(Report.alertType.duplicateIds, "In repository Accounts: " + (accounts.get(inner) + " and " + accounts.get(outer)));
                }
            }
        }

        // Check if any services have identical ids

        for (int outer = 0; outer < services.size() - 1; outer++) {
            for (int inner = outer + 1; inner < services.size(); inner++) {
                if (services.get(inner).getId().equals(services.get(outer).getId())) {
                    Report.add(Report.alertType.duplicateIds, "In repository Services: " + (services.get(inner) + " and " + services.get(outer)));
                }
            }
        }

        // Check if any requests have identical ids
        for (int outer = 0; outer < clearingHouse.size() - 1; outer++) {
            for (int inner = outer + 1; inner < clearingHouse.size(); inner++) {
                if (clearingHouse.get(inner).getId().equals(clearingHouse.get(outer).getId())) {
                    Report.add(Report.alertType.duplicateIds, "In repository ClearingHouse: " + (clearingHouse.get(inner) + " and " + clearingHouse.get(outer)));
                }
            }
        }

        // Check if any events have identical ids

        for (int outer = 0; outer < futures.size() - 1; outer++) {
            for (int inner = outer + 1; inner < futures.size(); inner++) {
                if (futures.get(inner).getId().equals(futures.get(outer).getId())) {
                    Report.add(Report.alertType.duplicateIds, "In repository Futures: " + (futures.get(inner) + " and " + futures.get(outer)));
                }
            }
        }
    }

    /**
     * This method looks through the ClearingHouse repository and makes sure all the services the requests reference are in fact valid
     * @param REQlist an ArrayList representing the ClearingHouse repository
     * @param SERlist an ArrayList representing the Services repository
     */
    public static void ReqsWithInvalidServices(ArrayList<WorkRequest> workRequests, ArrayList<Service> services) {

        for (int req = 0; req < workRequests.size(); req++) {
            Integer servID = workRequests.get(req).getServiceId();
            boolean isValid = false;
            for (int ser = 0; ser < services.size(); ser++) {
                if (servID.equals(services.get(ser).getId())) {
                    isValid = true;
                }
            }
            if (!isValid) {
                Report.add(Report.alertType.requestsWithInvalidServiceReferences, "WorkSlate ID: " + workRequests.get(req).getId());
            }
        }
    }

    /**
     * This method looks through the Futures repository and makes sure all the templates are valid
     * @param futures an ArrayList representing the futures repository
     */
    public static void futuresInvalidTemplates(ArrayList<Event> futures) {
        ArrayList<Event> invalids = new ArrayList<Event>();
        for (int index = 0; index < futures.size(); index++) {
            if (futures.get(index).getTemplate() == null) {
                Report.add(Report.alertType.futuresWithInvalidTemplates, "Future ID: " + futures.get(index).getId());
            }
        }
    }

    /**
     * This method looks through the Futures repository and checks if any futures are both enabled and expired
     * @param futures an ArrayList representing the futures repository
     */
    public static void enabledAndExpired(ArrayList<Event> futures) {
        ArrayList<Event> eAndE = new ArrayList<Event>();
        for (int index = 0; index < futures.size(); index++) {
            if (futures.get(index).getEnabled() && futures.get(index).getLastFired().before(Calendar.getInstance().getTime())) {
                Report.add(Report.alertType.enabledAndExpiredFutures, "Future ID: " + futures.get(index).getId());
            }
        }
    }
}
